package tw.right929.event
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.utils.Dictionary;
	
	/**
	 * 加強版的EventDispatcher。
	 */
	public class AdvancedEventDispatcher extends EventDispatcher
	{
		private var _eventSource:*;
		
		private var _map:Dictionary	=	new Dictionary();
		private var _mapCapture:Dictionary	=	new Dictionary();
		
		public function AdvancedEventDispatcher(target:IEventDispatcher=null)
		{
			super(target);
		}
		
		public function get eventSource():*
		{
			return _eventSource;
		}
		public function set eventSource(value:*):void
		{
			if(_eventSource == value)
				return;
			var old:*	=	_eventSource;
			bfs_eventSource(old , value);
			_eventSource	=	value;
			afs_eventSource(old , value);
		}
		private function bfs_eventSource(oldValue:* , newValue:*):void
		{
			if(oldValue && oldValue is IEventDispatcher)
			{
				for each(var type:* in _map)
				{
					for each(var l:* in type)
						oldValue.removeEventListener(l.type , _forwardEvent , l.useCapture);
				}
				for each(var typeC:* in _mapCapture)
				{
					for each(var lC:* in typeC)
						oldValue.removeEventListener(lC.type , _forwardEvent , lC.useCapture);
				}
			}
		}
		private function afs_eventSource(oldValue:* , newValue:*):void
		{
			if(newValue && newValue is IEventDispatcher)
			{
				for each(var type:* in _map)
				{
					for each(var l:* in type)
						newValue.addEventListener(l.type , _forwardEvent , l.useCapture , l.priority , l.useWeakReference);
				}
				for each(var typeC:* in _mapCapture)
				{
					for each(var lC:* in typeC)
						newValue.addEventListener(lC.type , _forwardEvent , lC.useCapture , lC.priority , lC.useWeakReference);
				}
			}
		}
		private function _forwardEvent(e:Event):void
		{
			dispatchEvent(e.clone());
		}

		override public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false) : void
		{
			if(_eventSource && _eventSource is IEventDispatcher)
				_eventSource.addEventListener(type , _forwardEvent , useCapture , priority , useWeakReference);
			
			super.addEventListener(type , listener , useCapture , priority , useWeakReference);
			
			if(useCapture)
			{
				if(_mapCapture[type])
				{
					if(_mapCapture[type][listener])
						return;
					_mapCapture[type][listener]	=	new $Listener(type , listener , useCapture , priority , useWeakReference);
				}
				else
				{
					_mapCapture[type]	=	new Dictionary();
					_mapCapture[type][listener]	=	new $Listener(type , listener , useCapture , priority , useWeakReference);
				}
			}
			else
			{
				if(_map[type])
				{
					if(_map[type][listener])
						return;
					_map[type][listener]	=	new $Listener(type , listener , useCapture , priority , useWeakReference);
				}
				else
				{
					_map[type]	=	new Dictionary();
					_map[type][listener]	=	new $Listener(type , listener , useCapture , priority , useWeakReference);
				}
			}
		}
		
		override public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false) : void
		{
			if(_eventSource && _eventSource is IEventDispatcher)
				_eventSource.removeEventListener(type , _forwardEvent , useCapture);
			
			super.removeEventListener(type, listener, useCapture);
			
			if(useCapture)
			{
				if(_mapCapture[type] && _mapCapture[type][listener])
					delete _mapCapture[type][listener];
			}
			else
			{
				if(_map[type] && _map[type][listener])
					delete _map[type][listener];
			}
		}
		
		/**
		 * 取得目前所有的事件偵聽式的type列表。
		 */
		public final function getAllEventListenerType():Array
		{
			var temp:Dictionary	=	new Dictionary(true);
			for(var type:* in _map)
			{
				for(var l:* in _map[type])
				{
					temp[type]	=	type;
					break;
				}
			}
			for(var typeC:* in _mapCapture)
			{
				for(var lC:* in _mapCapture[typeC])
				{
					temp[typeC]	=	typeC;
					break;
				}
			}
			
			var result:Array	=	new Array();
			for(var typeR:* in temp)
				result.push(typeR);
			
			return result;
		}
		
		/**
		 * 移除所有的事件偵聽式。
		 */
		public final function removeAllEventListener():void
		{
			for(var typeC:* in _mapCapture)
			{
				for(var lC:* in _mapCapture[typeC])
					removeEventListener(typeC , lC , true);
			}
			
			for(var type:* in _map)
			{
				for(var l:* in _map[type])
					removeEventListener(type , l , false);
			}
		}
		
		/**
		 * 移除指定事件的所有偵聽式。
		 */
		public final function removeEventListenerByType(type:String):Array
		{
			var result:Array	=	new Array();
			
			if(_mapCapture[type])
			{
				for(var lC:* in _mapCapture[type])
				{
					result.push(_mapCapture[type][lC]);
					removeEventListener(type , lC , true);
				}
			}
			
			if(_map[type])
			{
				for(var l:* in _map[type])
				{
					result.push(_map[type][l]);
					removeEventListener(type , l , false);
				}
			}
			
			return result;
		}
		
		/**
		 * 加入陣列(用removeEventListenerByType所傳回的陣列)中的所有偵聽式。
		 */
		public final function addEventListenerByArray(listeners:Array):void
		{
			for each(var l:* in listeners)
				addEventListener(l.type , l.listener , l.useCapture , l.priority , l.useWeakReference);
		}
	}
}

class $Listener
{
	public var type:String;
	public var listener:Function;
	public var useCapture:Boolean;
	public var priority:int;
	public var useWeakReference:Boolean;
	
	public function $Listener(type:String , listener:Function , useCapture:Boolean , priority:int , useWeakReference:Boolean)
	{
		this.type	=	type;
		this.listener	=	listener;
		this.useCapture	=	useCapture;
		this.priority	=	priority;
		this.useWeakReference	=	useWeakReference;
	}
}